#include "qmission.h"

#include <QUuid>
#include <QVariant>

QMission::QMission(enMissionType type)
{
    set_attribute(MISSION_TYPE,type);
    set_attribute(MISSION_LEVEL,10);
    set_attribute(MISSION_RETRIES,RETRY_TIMES);
    set_attribute(MISSION_STATUS,MS_READY);
    set_attribute(MISSION_PERIOD,1000);
    set_attribute(MISSION_TIME_OUT,500);
    set_attribute(MISSION_UUID,QUuid::createUuid().toString());
    set_attribute(MACHINE_ADDRESS,1);

    m_send_buffer=new uchar[SEND_BUFFER_SIZE];

    m_recv_buffer=new uchar[RECV_BUFFER_SIZE];
    set_attribute(RECV_MAX_LENGTH,RECV_BUFFER_SIZE);
}

QMission::~QMission()
{
    delete [] m_recv_buffer;
    delete [] m_send_buffer;
}

ushort QMission::get_crc(uchar *buffer, int size)
{
    int i;
    ushort crc_value=0xffff;
    int index=0;
    int s=size;
    while(0!=(size--))
    {
        if(index>=s)
        {
            return 0;
        }
        crc_value^=(buffer[index]&0xff);
        index++;
        for(i=0;i<8;i++)
        {
            if(0!=(crc_value&0x0001))
            {
                crc_value=(crc_value>>1)^0xa001;
            }
            else
            {
                crc_value=crc_value>>1;
            }
        }
    }
    crc_value=((crc_value>>8)&0xff)+((crc_value&0xff)<<8);
    return crc_value;
}

int QMission::get_recv_length()
{
    return m_recv_length;
}

int QMission::get_send_length()
{
    return m_send_length;
}

int QMission::need_to_do()
{
    int status=get_attribute(MISSION_STATUS).toInt();
    if(status!=MS_READY)
    {
        return 0;
    }
    if(get_attribute(MISSION_TYPE).toInt()<=MT_TEMP_READ)
    {
        return 5000;
    }
    int dis=m_last_time.msecsTo(QDateTime::currentDateTime());
    if(dis>=get_attribute(MISSION_PERIOD).toInt())
    {
        return dis-get_attribute(MISSION_PERIOD).toInt()+1;
    }
    else
    {
        return 0;
    }
}

void QMission::operator =(const QMission& ms)
{
    m_attribute=ms.m_attribute;
    m_last_time=ms.m_last_time;
    update_send_buffer();
}

void QMission::set_attribute(const QString &key, const QVariant &value)
{
    m_attribute.insert(key,value);
}

QVariant QMission::get_attribute(const QString &key, const QVariant &def)
{
    return m_attribute.value(key,def);
}


uchar*   QMission::get_send_buffer()
{
    return m_send_buffer;
}

uchar* QMission::get_recv_buffer()
{
    return m_recv_buffer;
}



void QMission::update_send_buffer()
{
    memset(m_send_buffer,0,SEND_BUFFER_SIZE);

    m_send_buffer[0]=get_attribute(MACHINE_ADDRESS).toInt();

    if(m_send_buffer[0]<=0 || m_send_buffer[0]>247)
    {
        set_attribute(MISSION_STATUS,MS_ERROR);
        return;
    }

    int type=get_attribute(MISSION_TYPE).toInt();
    int addr=get_attribute(DATA_ADDRESS).toInt();
    int len=get_attribute(DATA_LENGTH).toInt();

    if(addr<0 || addr>=65535 || len<0 || len>8)
    {
        set_attribute(MISSION_STATUS,MS_ERROR);
        return;
    }

    if(type==MT_TEMP_READ || type==MT_PERIOD_READ)
    {
        m_send_buffer[1]=0x03;
        m_send_buffer[2]=(addr>>8)&0xff;
        m_send_buffer[3]=addr&0xff;
        m_send_buffer[4]=(len>>8)&0xff;
        m_send_buffer[5]=len&0xff;
        m_send_length=8;
        m_recv_length=5+2*len;
    }
    else if(type==MT_TEMP_WRITE || type==MT_PERIOD_WRITE)
    {
        int value=get_attribute(MISSION_WRITE_DATA).toInt();
        m_send_buffer[1]=0x06;
        m_send_buffer[2]=(addr>>8)&0xff;
        m_send_buffer[3]=addr&0xff;
        m_send_buffer[4]=(value>>8)&0xff;
        m_send_buffer[5]=value&0xff;
        m_send_length=8;
        m_recv_length=8;
    }
    else
    {
        set_attribute(MISSION_STATUS,MS_ERROR);
        return;
    }
    ushort crc=get_crc(m_send_buffer,m_send_length-2);
    m_send_buffer[m_send_length-2]=(crc>>8)&0xff;
    m_send_buffer[m_send_length-1]=crc&0xff;
}

void QMission::ready()
{
    set_attribute(MISSION_STATUS,MS_READY);
    m_last_time=QDateTime::currentDateTime();
}
